﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Numerics;
using System.Security.Cryptography;
using System.IO;
using System.Text;
using RSA;


namespace RSA
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        static int keysize;
        static BigInteger[] klucz = new BigInteger[2];
        static int bctl;


        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button_GenerujKlucze_Click(object sender, EventArgs e)
        {
            generowaniekluczy();
        }

        protected void Button_Szyfruj_Click(object sender, EventArgs e)
        {
            if (FileUpload_Klucz.PostedFile.FileName == "" || FileUpload_Plik.PostedFile.FileName == "")
                alert("Zaladuj oba pliki");
            else
            {
                String filename = Server.MapPath(FileUpload_Klucz.PostedFile.FileName);

                FileInfo fi = new FileInfo(filename);
                BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open));
                int rozmiar = Convert.ToInt32(fi.Length / 2);
                klucz[0] = new BigInteger(br.ReadBytes(rozmiar));
                klucz[1] = new BigInteger(br.ReadBytes(rozmiar));
                keysize = rozmiar * 8;
                br.Close();

                szyfrowanie();
            }
        }

        protected void Button_Deszyfruj_Click(object sender, EventArgs e)
        {
            if (FileUpload_Klucz.PostedFile.FileName == "" || FileUpload_Plik.PostedFile.FileName == "")
                alert("Zaladuj oba pliki");
            else
            {
                String filename = Server.MapPath(FileUpload_Klucz.PostedFile.FileName);

                FileInfo fi = new FileInfo(filename);
                BinaryReader br = new BinaryReader(File.Open(filename, FileMode.Open));
                int rozmiar = Convert.ToInt32(fi.Length / 2);
                klucz[0] = new BigInteger(br.ReadBytes(rozmiar));
                klucz[1] = new BigInteger(br.ReadBytes(rozmiar));
                keysize = rozmiar * 8;
                br.Close();

                deszyfrowanie();
            }
        }

        private void alert(string msg)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("alert('");
            sb.Append(msg.Replace("\n", "\\n").Replace("\r", "").Replace("'", "\\'"));
            sb.Append("');");
            ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "showalert", sb.ToString(), true);
        }

        void szyfrowanie()
        {
            string we = Server.MapPath(FileUpload_Plik.PostedFile.FileName);
            string wy = we + ".enc";

            BinaryReader br = new BinaryReader(File.Open(we, FileMode.Open));
            BinaryWriter bw = new BinaryWriter(File.Open(wy, FileMode.Create));
            int blocksize = (keysize / 8) - 1;
            long blockcount = (br.BaseStream.Length / blocksize) + 1;
            bctl = blockcount.ToString().Length;
            for (long i = 0; i < blockcount; i++)
            {
                byte[] buf = br.ReadBytes(blocksize);
                BigInteger bi = new BigInteger(buf);
                BigInteger bo = encode(bi);
                buf = bo.getBytes().pad(blocksize + 1);
                bw.Write(buf);
            }
            bw.Close();
            br.Close();
            alert("Szyfrowanie udane. Zapisano jako " + FileUpload_Plik.PostedFile.FileName + ".enc");
        }

        void deszyfrowanie()
        {
            string we = Server.MapPath(FileUpload_Plik.PostedFile.FileName);
            string wy = we.Replace(".enc", ".dec");

            BinaryReader br = new BinaryReader(File.Open(we, FileMode.Open));
            BinaryWriter bw = new BinaryWriter(File.Open(wy, FileMode.Create));
            int blocksize = keysize / 8;
            long blockcount = (br.BaseStream.Length / blocksize);
            bctl = blockcount.ToString().Length;
            for (long i = 0; i < blockcount; i++)
            {
                byte[] buf = br.ReadBytes(blocksize);
                BigInteger bi = new BigInteger(buf);
                BigInteger bo = decode(bi);
                buf = bo.getBytes();
                if (i != (blockcount - 1))
                    buf = buf.pad(blocksize - 1);
                bw.Write(buf);
            }
            bw.Close();
            br.Close();

            alert("Deszyfrowanie udane. Zapisano jako " + FileUpload_Plik.PostedFile.FileName.Replace(".enc", ".dec"));
        }

        static BigInteger encode(BigInteger x)
        {
            BigInteger e = klucz[0];
            BigInteger n = klucz[1];
            return x.modPow(e, n);
        }

        static BigInteger decode(BigInteger c)
        {
            BigInteger d = klucz[0];
            BigInteger n = klucz[1];
            return c.modPow(d, n);
        }

        void generowaniekluczy()
        {
            int rozmiar = 0;
            String ro = TextBoxDlugoscKlucza.Text;
            if (TextBoxDlugoscKlucza.Text == "")
                alert("Nieprawidlowa wielkosc klucza ");
            else
            {
                rozmiar = Int32.Parse(ro);

                if (rozmiar > 2048 || rozmiar < 1)
                    alert("Nieprawidłowa wielkosc klucza.");
                else
                {

                    Random r = new Random();
                    BigInteger p = BigInteger.genPseudoPrime(rozmiar / 2, 1, r);
                    BigInteger q = BigInteger.genPseudoPrime(rozmiar / 2, 1, r);
                    BigInteger n = p * q;
                    BigInteger fi = (p - 1) * (q - 1);
                    BigInteger e = fi.genCoPrime(rozmiar, r);
                    BigInteger d = e.modInverse(fi);
                    String prvfname = Server.MapPath("~") + "prv." + rozmiar.ToString();
                    String pubfname = Server.MapPath("~") + "pub." + rozmiar.ToString();

                    int bytesize;
                    if (rozmiar % 8 == 0)
                        bytesize = rozmiar / 8;
                    else bytesize = (rozmiar + 8) / 8;

                    BinaryWriter prvbw = new BinaryWriter(File.Open(prvfname, FileMode.Create));
                    prvbw.Write(d.getBytes().pad(bytesize));
                    prvbw.Write(n.getBytes().pad(bytesize));
                    prvbw.Close();
                    BinaryWriter pubbw = new BinaryWriter(File.Open(pubfname, FileMode.Create));
                    pubbw.Write(e.getBytes().pad(bytesize));
                    pubbw.Write(n.getBytes().pad(bytesize));
                    pubbw.Close();
                    alert("Operacja udana. Stworzono klucz prywatny - prv." + rozmiar.ToString() + " i publiczny - pub." + rozmiar.ToString());

                    /*
                    Label1.Text = "p = " + p.ToString();
                    Label2.Text = "q = " + q.ToString();
                    Label3.Text = "n = " + n.ToString();
                    Label4.Text = "fi = " + fi.ToString();
                    Label5.Text = "e = " + e.ToString();
                    Label6.Text = "d = " + d.ToString();
                    */
                }
            }
        }
    }
}